package org.example.list;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * @author wujiale
 * 单向列表
 **/
public class SinglyLinkedList implements Iterable<Integer>{

    //头指针
    private Node head = null;

    @Override
    public Iterator<Integer> iterator() {

        return new Iterator<Integer>() {
            Node p = head;
            @Override
            public boolean hasNext() {
                return p!=null;
            }

            @Override
            public Integer next() {
                int v = p.value;
                p = p.next;
                return v;
            }
        };
    }

    /**
     * 节点类
     */
    private static class Node{
        //值
        int value;
        //下个节点指针
        Node next;

        public Node(int value,Node node) {
            this.value = value;
            this.next = node;
        }
    }

    public void addFirst(int value){
        // 1.链表为空
        /*head = new Node(value, null);*/
        // 2.链表非空
        head = new Node(value,head);
    }

    /**
     * 便利 需掌握
     * @param consumer 函数式接口
     */
    public void loop1(Consumer<Integer> consumer){
        //指向第一个节点
        Node pointer = head;
        while (pointer!=null){
            consumer.accept(pointer.value);
            pointer =  pointer.next;
        }
    }

    private Node getLast(){
        if(head == null){
            return null;
        }
        Node p = head;
        while (p.next != null){
            p = p.next;
        }
        return p;
    }

    public void loop3(Consumer<Integer> before,Consumer<Integer> after){

        recursion(head,before,after);

    }
    /**
     * 针对某个节点要进行的操作
     * @param current 当前处理节点
     */
    private void recursion(Node current,Consumer<Integer> before,Consumer<Integer> after){
        if (current == null){
            return;
        }
        before.accept(current.value);
        recursion(current.next,before,after);
        after.accept(current.value);
    }

    public void addLast(int value){
        Node last = getLast();
        if(last == null){
            addFirst(value);
        }else {
            last.next = new Node(value,null);
        }
    }

    /**
     * 便利 需掌握
     * @param consumer 函数式接口
     */
    public void loop2(Consumer<Integer> consumer){
        for(Node p = head;p != null;p = p.next){
          consumer.accept(p.value);
        }
    }

    private Node getNode(int index){
        int i = 0;
        for (Node p = head;p!=null;p = p.next,i++){
            if(index == i){
                return p;
            }
        }
        return null;
    }

    public int get(int index){
        Node node = getNode(index);
        if(node==null){
            throw new IndexOutOfBoundsException(String.format("index [%d}",index));
        }else {
            return node.value;
        }
    }

    public void addLast(int first, int... rest) {

        Node sublist = new Node(first, null);
        Node curr = sublist;
        for (int value : rest) {
            curr.next = new Node(value, null);
            curr = curr.next;
        }

        Node last = getLast();
        if (last == null) {
            this.head = sublist;
            return;
        }
        last.next = sublist;
    }

    public void insert(int index,int value){
        if (index==0){
            //头部插入
            addFirst(value);
            return;
        }
        // 找到插入位置的前驱节点
        Node prev = getNode(index-1);
        if (prev != null) {
            prev.next = new Node(value,prev.next);
        }else {
            throw new IllegalArgumentException(String.format("index [%d]",index));
        }

    }

    public Integer removeFirst(){
        if(head == null){
            return null;
        }else{
            int result = head.value;
            head = head.next;
            return result;
        }
    }

    public Integer remove(int index){
        if(index==0){
            return removeFirst();
        }
        Node prev = getNode(index-1);
        if(prev==null){
            throw new IndexOutOfBoundsException(String.format("index [%d}",index));
        }else {
            int result = prev.next.value;
            prev.next = prev.next.next;
            return result;
        }
    }



    public static void main(String[] args) {
        SinglyLinkedList singlyLinkedList = new SinglyLinkedList();
        singlyLinkedList.addFirst(1);
        singlyLinkedList.addFirst(2);
        singlyLinkedList.addFirst(3);
        /*singlyLinkedList.loop2(System.out::println);
        System.out.println("---------------");
        singlyLinkedList.addLast(1);
        singlyLinkedList.addLast(2);
        singlyLinkedList.addLast(3);
        singlyLinkedList.forEach(System.out::println);
        System.out.println("get2---------------");
        System.out.println(singlyLinkedList.get(2));
        //System.out.println(singlyLinkedList.get(10));
        singlyLinkedList.insert(5,10);
        singlyLinkedList.insert(3,10);
        System.out.println("insert---------");
        singlyLinkedList.forEach(System.out::println);
        singlyLinkedList.insert(0,30);
        System.out.println("insert2-======---");
        singlyLinkedList.forEach(System.out::println);
        Integer integer = singlyLinkedList.removeFirst();
        System.out.println("removeFirst"+integer);
        singlyLinkedList.remove(0);
        System.out.println("remove0----------");
        singlyLinkedList.forEach(System.out::println);*/

        System.out.println("loop3");
        singlyLinkedList.loop3(System.out::println, System.out::println);
    }
}


